home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 25
/
Aminet 25 (1998)(GTI - Schatztruhe)[!][Jun 1998].iso
/
Aminet
/
util
/
pack
/
xpk_Source.lha
/
xpk_Source
/
xpkmaster
/
xpkmaster.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-03-26
|
20KB
|
709 lines
#ifndef XPKMASTER_XPKMASTER_C
#define XPKMASTER_XPKMASTER_C
/* Routinesheader
Name: xpkmaster.c
Main: xpkmaster
Versionstring: $VER: xpkmaster.c 1.13 (21.02.1998)
Author: SDI
Distribution: Freeware
Description: the main xpk functions
1.0 09.10.96 : first real version
1.1 27.12.96 : removed 1.3 specific functions
1.2 10.01.97 : corrected XpkPack's abort
1.3 11.01.97 : corrected mem bug (reported by Laurent Kempe)
1.4 30.01.97 : hopefully fixed mem bug finally
1.5 31.01.97 : bug still occured
1.6 01.03.97 : added NoPack stuff to XpkWrite and XpkPack
1.7 24.03.97 : fixed XpkPack
1.8 25.03.97 : added AutoPasswd
1.9 28.03.97 : moved autopassword into xpkopen
1.10 01.04.97 : fixed NoPack error
1.11 19.12.97 : added xfdmaster support, made MBUG defines
1.12 09.01.98 : better passkey handling
1.13 21.02.98 : uses new style register definition
*/
/**************************************************/
#ifdef __MAXON__ /**/
#define MBUGDEF ULONG maxon_bug; /**/
#define MBUG maxon_bug = (ULONG) /**/
#else /**/
#define MBUG /**/
#define MBUGDEF /**/
#endif /**/
/**************************************************/
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/dos.h>
#include <proto/utility.h>
#include <proto/xpkmaster.h>
#include <proto/xfdmaster.h>
#include <proto/xpksub.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/tasks.h>
#include <dos/dos.h>
#include "xpkmaster.h"
#include "texts.h"
#ifdef USE_POWERPACKER
#include <proto/powerpacker.h>
#include <libraries/ppbase.h>
#endif
#ifdef SUPPORT_A4
LONG XpkOpenA4NAME(struct XpkFib **xfh, struct TagItem *tags, ULONG a4);
#ifdef __SASC
#pragma libcall XpkBase XpkOpenA4NAME 036 C9803
#else
#pragma amicall(XpkBase,0x36,XpkOpenA4NAME(a0,a1,a4))
#endif
#else
#define XpkOpenA4NAME XpkOpen
#endif
/**************************************************************************
*
* XpkPack() - pack a file
*
*/
ASM(LONG) LIBXpkPack(REG(a0, struct TagItem *tags) A4PROTO)
{
struct XpkBuffer *xbuf = 0;
STRPTR buf;
LONG totlen, res, chunklen;
if(!FindTagItem(XPK_PackMethod, tags))
return XPKERR_BADPARAMS;
if((res = XpkOpenA4NAME((struct XpkFib **) &xbuf, tags A4SUPP)))
return res;
totlen = xbuf->xb_InLen;
CurrentTime(&xbuf->xb_Secs, &xbuf->xb_Mics); /* Start the clock */
xbuf->xb_Prog.xp_Type = XPKPROG_START;
xbuf->xb_Prog.xp_ULen = totlen;
if(callprogress(xbuf))
return XpkClose((struct XpkFib *) xbuf);
while(totlen > 0)
{
chunklen = xbuf->xb_Fib.xf_NLen;
if(!(buf = (STRPTR) hookread(xbuf, XIO_READ, NULL, chunklen)))
break;
if(XpkWrite((struct XpkFib *) xbuf, buf, chunklen))
break;
totlen -= chunklen;
xbuf->xb_Prog.xp_Type = XPKPROG_MID; /* Progress report */
xbuf->xb_Prog.xp_UCur += chunklen;
xbuf->xb_Prog.xp_CCur = xbuf->xb_Fib.xf_CCur;
if(callprogress(xbuf))
return XpkClose((struct XpkFib *) xbuf);
}
if(xbuf->xb_Prog.xp_Type)
{
xbuf->xb_Prog.xp_Type = XPKPROG_END;
xbuf->xb_Prog.xp_CCur += xbuf->xb_Headers.h_LocSize;
xbuf->xb_Prog.xp_Activity = xbuf->xb_Result ?
strings[TXT_ABORTED] : xbuf->xb_LastMsg;
callprogress(xbuf); /* Call the hook one last time */
}
return XpkClose((struct XpkFib *) xbuf);
}
/*********************************************************************
*
* XpkUnpack - unpack a file
*
*/
ASM(LONG) LIBXpkUnpack(REG(a0, struct TagItem *tags) A4PROTO)
{
struct XpkBuffer *xbuf = NULL;
STRPTR pointer;
LONG len, res;
#ifdef DEBUG
DebugRunTime("XpkUnpack");
#endif
if((res = XpkOpenA4NAME((struct XpkFib **) &xbuf, tags A4SUPP)))
return res;
if(xbuf->xb_Flags & XMF_PACKING)
{
xbuf->xb_Result = XPKERR_BADPARAMS;
goto Abort;
}
CurrentTime(&xbuf->xb_Secs, &xbuf->xb_Mics); /* Start the clock */
xbuf->xb_Prog.xp_Type = XPKPROG_START; /* Initialize progress */
xbuf->xb_Prog.xp_ULen = xbuf->xb_Fib.xf_ULen;
if(callprogress(xbuf))
goto Abort;
if(!hookwrite(xbuf, XIO_TOTSIZE, NULL, xbuf->xb_Fib.xf_ULen + XPK_MARGIN))
{
#ifdef DEBUG
DebugError("XpkUnpack: XIO_TOTSIZE failed");
#endif
goto Abort;
}
if(!(pointer = (STRPTR) hookwrite(xbuf, XIO_GETBUF, 0, xbuf->xb_Fib.xf_NLen)))
{
#ifdef DEBUG
DebugError("XpkUnpack: XIO_GETBUF failed (a)");
#endif
goto Abort;
}
#ifdef DEBUG
if(xbuf->xb_Result)
DebugError("XpkUnpack: failure before unpackloop");
#endif
while((len = XpkRead((struct XpkFib *) xbuf, pointer, xbuf->xb_Fib.xf_NLen)) > 0)
{
if(!hookwrite(xbuf, XIO_WRITE, pointer, len))
{
#ifdef DEBUG
DebugError("XpkUnpack: XIO_WRITE failed");
#endif
goto Abort;
}
xbuf->xb_Prog.xp_Type = XPKPROG_MID; /* Progress report */
xbuf->xb_Prog.xp_CCur = xbuf->xb_Fib.xf_CCur;
xbuf->xb_Prog.xp_UCur = xbuf->xb_Fib.xf_UCur;
if(callprogress(xbuf))
goto Abort;
if(!(pointer = (STRPTR) hookwrite(xbuf, XIO_GETBUF, NULL, xbuf->xb_Fib.xf_NLen)))
{
#ifdef DEBUG
DebugError("XpkUnpack: XIO_GETBUF failed (b)");
#endif
goto Abort;
}
}
xbuf->xb_Result = len;
#ifdef DEBUG
if(xbuf->xb_Result)
DebugError("XpkUnpack: XpkRead failed with %ld", xbuf->xb_Result);
#endif
if(xbuf->xb_Prog.xp_Type)
{
xbuf->xb_Prog.xp_Type = XPKPROG_END;
xbuf->xb_Prog.xp_Activity = xbuf->xb_Result ? strings[TXT_ABORTED] : xbuf->xb_LastMsg;
callprogress (xbuf); /* Call the hook one last time */
}
Abort:
return XpkClose((struct XpkFib *) xbuf);
}
/*********************************************************************
*
* XpkOpen - open a file for packing/unpacking
*
*/
ASM(LONG) LIBXpkOpen(REG(a0, struct XpkBuffer **xbufp),
REG(a1, struct TagItem *tags) A4PROTO)
{
#if defined(DEBUG) && defined(SUPPORT_A4)
DebugRunTime("XpkOpen: A4 = %ld", a4);
#elif defined(DEBUG)
DebugRunTime("XpkOpen");
#endif
return xpkopen(xbufp, tags, 0 A4SUPP);
}
/**************************************************************************
*
* XpkExamine() - inspect a compressed file
*
*/
ASM(LONG) LIBXpkExamine(REG(a0, struct XpkFib *fib),
REG(a1, struct TagItem *tags) A4PROTO)
{
struct XpkBuffer *dummy;
LONG res;
#if defined(DEBUG) && defined(SUPPORT_A4)
DebugRunTime("XpkExamine: A4 = %ld", a4);
#elif defined(DEBUG)
DebugRunTime("XpkExamine");
#endif
if((res = xpkopen(&dummy, tags, 1 A4SUPP)))
return res;
CopyMem(dummy, fib, sizeof(struct XpkFib));
/* copies the entries of XpkFib
*fib = dummy->Fib works too, but calls it's own copy-function */
return XpkClose((struct XpkFib *) dummy);
}
/**************************************************************************
*
* XpkRead() - read one chunk from a compressed file
*
*/
ASM(LONG) LIBXpkRead(REG(a0, struct XpkBuffer *xbuf), REG(a1, STRPTR buf),
REG(d0, ULONG len))
{
MBUGDEF
#ifdef DEBUG
DebugRunTime("XpkRead: buf %08lx, size %ld", buf, len);
#endif
if(!xbuf)
return XPKERR_NOFUNC;
if(xbuf->xb_Flags & XMF_EOF)
return 0;
switch(xbuf->xb_Format)
{
/*********************** Unpack standard XPK *******************/
case XPKMODE_UPSTD:
{
struct XpkSubParams *xpar;
struct Library *XpkSubBase = xbuf->xb_SubBase;
XpkChunkHeader *lochdr = &(xbuf->xb_Headers.h_Loc);
LONG ulen, clen, rclen, lochdrsize = xbuf->xb_Headers.h_LocSize;
ULONG csum;
if(lochdr->xch_Word.xchw_Type == XPKCHUNK_END)
return 0;
if((MBUG hchecksum((STRPTR) lochdr, lochdrsize)))
{
#ifdef DEBUG
DebugError("XpkRead: hchecksum(,%ld) failed", lochdrsize);
#endif
return(xbuf->xb_Result = XPKERR_CHECKSUM);
}
if(xbuf->xb_Headers.h_Glob.xsh_Flags & XPKSTREAMF_LONGHEADERS)
ulen = lochdr->xch_Long.xchl_ULen, clen = lochdr->xch_Long.xchl_CLen;
else
ulen = lochdr->xch_Word.xchw_ULen, clen = lochdr->xch_Word.xchw_CLen;
rclen = ROUNDLONG(clen);
if(lochdr->xch_Word.xchw_Type == XPKCHUNK_RAW)
{
if(!(MBUG hookread(xbuf, XIO_READ, buf, rclen + lochdrsize)))
return xbuf->xb_Result;
if(!(xbuf->xb_Flags & XMF_NOCRC))
if((csum=cchecksum((ULONG *) buf, rclen >>2)) != lochdr->xch_Word.xchw_CChk)
{
#ifdef DEBUG
DebugError("XpkRead: cchecksum(,%ld) = %lx != %lx failed", rclen >> 2, csum, (ULONG) lochdr->xch_Word.xchw_CChk);
#endif
return (xbuf->xb_Result = XPKERR_CHECKSUM);
}
CopyMem(buf + rclen, lochdr, lochdrsize);
}
else if(lochdr->xch_Word.xchw_Type == XPKCHUNK_PACKED)
{
xpar = &xbuf->xb_PackParam;
if(!(xpar->xsp_InBuf = hookread(xbuf, XIO_READ, NULL, rclen + lochdrsize)))
return xbuf->xb_Result;
if(!(xbuf->xb_Flags & XMF_NOCRC))
if((csum=cchecksum((ULONG *)xpar->xsp_InBuf, rclen >> 2)) != lochdr->xch_Word.xchw_CChk)
{
#ifdef DEBUG
DebugError("XpkRead: cchecksum(,%ld) = %lx != %lx failed", rclen >>2 , csum, (ULONG) lochdr->xch_Word.xchw_CChk);
#endif
return (xbuf->xb_Result = XPKERR_CHECKSUM);
}
xbuf->xb_Flags |= XMF_INITED;
xpar->xsp_InLen = clen;
xpar->xsp_OutLen = ulen;
xpar->xsp_OutBuf = buf;
xpar->xsp_OutBufLen = ulen;
xpar->xsp_Number = 0;
xpar->xsp_Password = xbuf->xb_Password;
xpar->xsp_LibVersion = xbuf->xb_Headers.h_Glob.xsh_SubVrs;
if((xbuf->xb_Result = XpksUnpackChunk(xpar)))
return xbuf->xb_Result;
CopyMem((STRPTR) xpar->xsp_InBuf + rclen, lochdr, lochdrsize);
}
else
return (xbuf->xb_Result = XPKERR_CORRUPTPKD);
updatefib(xbuf);
return ulen;
}
#ifdef USE_POWERPACKER
/********************* Unpack powerpacked file ****************/
case XPKMODE_UPPP:
{
struct Library *PPBase = xbuf->xb_SubBase;
STRPTR inbuf, inbufend;
if(!(inbuf = (STRPTR) hookread(xbuf, XIO_READ, NULL, xbuf->xb_InLen - 4)))
return xbuf->xb_Result;
inbufend = inbuf + xbuf->xb_InLen - 4;
ppDecrunchBuffer(inbufend, buf, (ULONG *) inbuf, DECR_NONE);
xbuf->xb_Fib.xf_CCur = xbuf->xb_InLen;
xbuf->xb_Fib.xf_UCur = xbuf->xb_Fib.xf_ULen;
xbuf->xb_Fib.xf_NLen = 0;
xbuf->xb_Flags |= XMF_EOF;
return (LONG) xbuf->xb_Fib.xf_ULen;
}
#endif /* USE_POWERPACKER */
/**************************** xfdmaster file **************************/
case XPKMODE_UPXFD:
{
struct xfdMasterBase *xfdMasterBase = (struct xfdMasterBase *) xbuf->xb_SubBase;
struct xfdBufferInfo *xbi = xbuf->xb_xfd;
xbi->xfdbi_Flags = XFDFF_USERTARGET;
xbi->xfdbi_UserTargetBuf = buf;
xbi->xfdbi_UserTargetBufLen = len;
if((xbuf->xb_Fib.xf_Flags & XPKFLAGS_KEY32) &&
(xbuf->xb_Flags & XMF_KEY32))
xbi->xfdbi_Special = &xbuf->xb_PassKey32;
else if((xbuf->xb_Fib.xf_Flags & XPKFLAGS_KEY16) &&
(xbuf->xb_Flags & XMF_KEY16))
xbi->xfdbi_Special = &xbuf->xb_PassKey16;
else if(xbuf->xb_Fib.xf_Flags & XPKFLAGS_PASSWORD)
xbi->xfdbi_Special = xbuf->xb_Password;
if(!xfdDecrunchBuffer(xbi))
{
switch(xbi->xfdbi_Error)
{
case XFDERR_NOMEMORY: xbuf->xb_Result = XPKERR_NOMEM; break;
case XFDERR_WRONGPASSWORD: case XFDERR_WRONGKEY:
xbuf->xb_Result = XPKERR_WRONGPW; break;
case XFDERR_CORRUPTEDDATA: xbuf->xb_Result = XPKERR_CORRUPTPKD; break;
case XFDERR_BETTERCPU: xbuf->xb_Result = XPKERR_WRONGCPU; break;
default: xbuf->xb_Result = XPKERR_UNKNOWN; break;
}
#ifdef DEBUG
DebugRunTime("XpkRead: xfd failed with %ld", xbuf->xb_Result);
#endif
return xbuf->xb_Result;
} /* xfdDecrunchBuffer */
xbuf->xb_Fib.xf_CCur = xbuf->xb_InLen;
xbuf->xb_Fib.xf_UCur = xbuf->xb_Fib.xf_ULen;
xbuf->xb_Fib.xf_NLen = 0;
xbuf->xb_Flags |= XMF_EOF;
#ifdef DEBUG
DebugRunTime("XpkRead: xfd returns %ld", xbuf->xb_Fib.xf_ULen);
#endif
return (LONG) xbuf->xb_Fib.xf_ULen;
}
/********************* Unpack unpacked file *******************/
case XPKMODE_UPUP:
{
ULONG leftlen = xbuf->xb_Fib.xf_ULen - xbuf->xb_Fib.xf_CCur;
if(leftlen > len)
leftlen = len;
else
xbuf->xb_Flags |= XMF_EOF;
if(!(MBUG hookread(xbuf, XIO_READ, buf, leftlen)))
return xbuf->xb_Result;
xbuf->xb_Fib.xf_CCur += leftlen;
xbuf->xb_Fib.xf_UCur += leftlen;
xbuf->xb_Fib.xf_NLen = Min(xbuf->xb_InLen -
xbuf->xb_Fib.xf_UCur, DEFAULTCHUNKSIZE) + XPK_MARGIN;
return (LONG) leftlen;
}
}
return xbuf->xb_Result;
}
/**************************************************************************
*
* XpkWrite() - write a chunk to a compressed file
*
*/
ASM(LONG) LIBXpkWrite(REG(a0, struct XpkBuffer *xbuf), REG(a1, STRPTR buf),
REG(d0, ULONG ulen))
{
struct Library *XpkSubBase = xbuf->xb_SubBase;
struct XpkSubParams *xpar;
struct Headers *head = &xbuf->xb_Headers;
LONG clen, rclen, outbuflen;
UWORD end[2] = {0,0}; /* last ULONG of buffer, when not longword bounded */
UBYTE type;
STRPTR outbuf;
MBUGDEF
if(!xbuf->xb_FirstChunk)
xbuf->xb_FirstChunk = ulen;
if(ulen > xbuf->xb_FirstChunk)
return (xbuf->xb_Result = XPKERR_BADPARAMS);
if(xbuf->xb_Flags & XMF_NOPACK) /* no packing */
{
hookwrite(xbuf, XIO_WRITE, buf, ulen);
xbuf->xb_Fib.xf_UCur += ulen;
xbuf->xb_Fib.xf_CCur += ulen;
xbuf->xb_Fib.xf_NLen = Min(xbuf->xb_InLen - xbuf->xb_Fib.xf_UCur,
(LONG) xbuf->xb_ChunkSize);
return xbuf->xb_Result;
}
/******************* Write the GlobHdr ********************/
if(!(xbuf->xb_Flags & XMF_GLOBHDR))
{
if(!xbuf->xb_Password)
CopyMem(buf, head->h_Glob.xsh_Initial, Min(16, ulen));
xbuf->xb_Flags |= XMF_GLOBHDR;
if(!(MBUG hookwrite(xbuf, XIO_WRITE, &head->h_Glob,
sizeof(struct XpkStreamHeader))))
return xbuf->xb_Result;
xbuf->xb_Fib.xf_CCur += sizeof(struct XpkStreamHeader);
}
/******************* Allocate the buffer *****************/
outbuflen = ROUNDLONG(ulen + (ulen>>5) + head->h_LocSize) + XPK_MARGIN;
if(!(outbuf = (STRPTR) hookwrite(xbuf, XIO_GETBUF, NULL, outbuflen)))
return xbuf->xb_Result;
outbuf += head->h_LocSize;
/* compress to behind local header. This is needed by mem-out hook! */
if(ulen < xbuf->xb_SubInfo->xi_MinPkInChunk)
goto copychunk;
/******************* Pack the chunk **********************/
xpar = &xbuf->xb_PackParam;
xpar->xsp_InBuf = buf;
xpar->xsp_InLen = ulen;
xpar->xsp_OutBuf = outbuf;
xpar->xsp_OutBufLen = outbuflen - head->h_LocSize;
xpar->xsp_Number += 1;
xpar->xsp_Mode = xbuf->xb_PackingMode;
xpar->xsp_Password = xbuf->xb_Password;
xpar->xsp_LibVersion = xbuf->xb_SubInfo->xi_LibVersion;
xbuf->xb_Result = XpksPackChunk(xpar);
xbuf->xb_Flags |= XMF_INITED;
type = XPKCHUNK_PACKED;
clen = xpar->xsp_OutLen;
if(xbuf->xb_Result == XPKERR_EXPANSION)
{
xbuf->xb_Result = 0;
copychunk:
type = XPKCHUNK_RAW;
clen = ulen;
outbuf = buf;
}
if(xbuf->xb_Result)
return xbuf->xb_Result;
/******************* Write the chunk **********************/
head->h_Loc.xch_Word.xchw_Type = type;
if(head->h_Glob.xsh_Flags & XPKSTREAMF_LONGHEADERS)
{
head->h_Loc.xch_Long.xchl_ULen = ulen;
head->h_Loc.xch_Long.xchl_CLen = clen;
}
else
{
head->h_Loc.xch_Word.xchw_ULen = (WORD) ulen;
head->h_Loc.xch_Word.xchw_CLen = (WORD) clen;
}
if((rclen = clen&3))
{
clen -= rclen;
CopyMem(outbuf+clen, &end, rclen); /* copy the remaining bytes (max 3) */
}
head->h_Loc.xch_Word.xchw_CChk = cchecksum((ULONG *) outbuf, clen >> 2)
^ end[0] ^ end[1];
/* add the rest bytes to the checksum */
head->h_Loc.xch_Word.xchw_HChk = 0;
head->h_Loc.xch_Word.xchw_HChk = hchecksum((STRPTR) &head->h_Loc, head->h_LocSize);
if(!(MBUG hookwrite(xbuf, XIO_WRITE, &head->h_Loc, head->h_LocSize)))
return xbuf->xb_Result;
if(!(MBUG hookwrite(xbuf, XIO_WRITE, outbuf, clen)))
return xbuf->xb_Result;
if(rclen)
{
if(!(MBUG hookwrite(xbuf, XIO_WRITE, &end, 4)))
return xbuf->xb_Result;
clen += 4;
}
head->h_Glob.xsh_ULen += ulen;
xbuf->xb_Fib.xf_UCur += ulen;
xbuf->xb_Fib.xf_CCur += head->h_LocSize + clen;
xbuf->xb_Fib.xf_NLen = Min(max(xbuf->xb_InLen, head->h_Glob.xsh_ULen) -
xbuf->xb_Fib.xf_UCur, (LONG) xbuf->xb_ChunkSize);
return xbuf->xb_Result;
}
/**************************************************************************
*
* XpkSeek() - move around on a compressed file
*
*/
ASM(LONG) LIBXpkSeek(REG(a0, struct XpkBuffer *xbuf), REG(d0, LONG dist),
REG(d1, ULONG mode))
{
xbuf->xb_Result = XPKERR_NOFUNC;
parsegettags(xbuf);
return xbuf->xb_Result;
}
/**************************************************************************
*
* XpkClose() - finish (de)compressing an XPK file
*
*/
ASM(LONG) LIBXpkClose(REG(a0, struct XpkBuffer *xbuf))
{
struct Library *XpkSubBase = xbuf->xb_SubBase;
if(!xbuf)
return 0;
#ifdef DEBUG
if(xbuf->xb_Result)
DebugError("XpkClose: failed (%ld) before XpkClose", xbuf->xb_Result);
#endif
if(xbuf->xb_Format == XPKMODE_PKSTD)
{
struct Headers *head = &xbuf->xb_Headers;
LONG outlen;
if(!xbuf->xb_Result && !(xbuf->xb_Flags & XMF_GLOBHDR|XMF_NOPACK))
{
hookwrite(xbuf, XIO_WRITE, &head->h_Glob, sizeof(struct XpkStreamHeader));
#ifdef DEBUG
if(xbuf->xb_Result) DebugError("XpkClose: failed to write globhdr");
#endif
xbuf->xb_Fib.xf_CCur += sizeof(struct XpkStreamHeader);
}
if(!xbuf->xb_Result && !(xbuf->xb_Flags & XMF_NOPACK))
{
/******************* Write final chunk header *****************/
memset(&head->h_Loc, 0, head->h_LocSize);
head->h_Loc.xch_Word.xchw_Type = XPKCHUNK_END;
head->h_Loc.xch_Word.xchw_HChk = 0;
head->h_Loc.xch_Word.xchw_HChk =
hchecksum((STRPTR) &head->h_Loc, head->h_LocSize);
hookwrite(xbuf, XIO_WRITE, &head->h_Loc, head->h_LocSize);
#ifdef DEBUG
if(xbuf->xb_Result) DebugError("XpkClose: failed to write lochdr");
#endif
xbuf->xb_Fib.xf_CCur += head->h_LocSize;
outlen = xbuf->xb_Fib.xf_CCur;
/********************** Write global header *******************/
hookwrite(xbuf, XIO_SEEK, NULL, -outlen);
#ifdef DEBUG
if(xbuf->xb_Result) DebugError("XpkClose: failed to reset output");
#endif
head->h_Glob.xsh_Pack = XPK_COOKIE;
head->h_Glob.xsh_CLen = outlen - 8;
head->h_Glob.xsh_HChk = 0;
head->h_Glob.xsh_HChk =
hchecksum((STRPTR) &head->h_Glob, sizeof(struct XpkStreamHeader));
hookwrite(xbuf, XIO_WRITE, &head->h_Glob, sizeof(struct XpkStreamHeader));
#ifdef DEBUG
if(xbuf->xb_Result) DebugError("XpkClose: failed updating globalhdr");
#endif
hookwrite(xbuf, XIO_SEEK, 0, outlen - sizeof(struct XpkStreamHeader));
#ifdef DEBUG
if(xbuf->xb_Result) DebugError("XpkClose: failed to SEEK to end of output");
#endif
}
xbuf->xb_Fib.xf_CLen = xbuf->xb_Fib.xf_CCur;
xbuf->xb_Fib.xf_ULen = xbuf->xb_Fib.xf_UCur;
/*************************** Shut down *************************/
if(xbuf->xb_Flags & XMF_INITED)
XpksPackFree(&xbuf->xb_PackParam);
}
else if(xbuf->xb_Format == XPKMODE_UPSTD && xbuf->xb_Flags & XMF_INITED)
XpksUnpackFree(&xbuf->xb_PackParam);
hookread(xbuf, xbuf->xb_Result ? XIO_ABORT : XIO_FREE, NULL, 0);
#ifdef DEBUG
if(xbuf->xb_Result) DebugError("XpkClose: failed read ABORT/FREE");
#endif
hookwrite(xbuf, xbuf->xb_Result ? XIO_ABORT : XIO_FREE, NULL, 0);
#ifdef DEBUG
if(xbuf->xb_Result) DebugError("XpkClose: failed write ABORT/FREE");
#endif
parsegettags(xbuf); /* Send information to the user */
#ifdef DEBUG
DebugRunTime("XpkClose: InLen %ld, CLen %ld, ULen %ld, ID %.4s", xbuf->xb_InLen,
xbuf->xb_Fib.xf_CLen, xbuf->xb_Fib.xf_ULen, &xbuf->xb_Fib.xf_ID);
#endif
return freebufs(xbuf);
}
#endif /* XPKMASTER_XPKMASTER_C */